'''
2-3 构建网络
使用卷积网络
两个卷积层参数: f:8*3*3(8个尺寸为3*3的卷积核)，s=1, p=1
池化层参数: f:2*2, s=2, p=0   (s步长，p填充的边界尺寸)
每一个卷积层中采用的激活函数为ReLU函数，只有最后一层采用Softmax函数输出分类结果
'''
import torch.nn as nn
class ICNET(nn.Module):
    def __init__(self):
        super(ICNET,self).__init__()   #继承类
        self.ConvNet = nn.Sequential(     #nn搭建卷积网络
            nn.Conv2d(in_channels=3,out_channels=8,kernel_size=3,stride=1,padding=1,bias=False),  #尺寸：128，128，8
            # in_channels 代表卷积层输入个数，out_channels 代表卷积层输出的个数，kernel_size 代表卷积核尺寸，stride 代表步长，padding 代表填充的边界尺寸，bias 代表是否存在偏置
            nn.ReLU(inplace=True),
            nn.Conv2d(in_channels=8,out_channels=8,kernel_size=3,stride=1,padding=1,bias=False), #尺寸：128,128,8
            nn.ReLU(inplace=True),
            nn.MaxPool2d(kernel_size=2,stride=2,padding=0), #尺寸：64,64,8
        )

        self.LinNet = nn.Sequential(          #nn模块搭建网络
            nn.Linear(64*64*8,1000),
            nn.ReLU(inplace=True),
            nn.Linear(1000,1000),
            nn.ReLU(inplace=True),   #每一个ReLU函数都增加了一个inplace参数，该参数为True表示每次进行ReLU函数的计算时都进行覆盖操作（如x=x+1），不会申请新的内存空间，从而大大节省了内存空间
            nn.Linear(1000,2),
            nn.Softmax(dim=1)            # Softmax 分类激活函数
    )

    def forward(self,x):
        x = self.ConvNet(x)           # 将x传入卷积网络
        x = x.view(x.size(0),64*64*8)  # 展成一维数组，全连接层的输入要求是一维数组
        # x.size(0)代表最小批次，即训练程序中设置的minibatch参数，第二个参数代表Tensor变量展成一维数组的元素个数
        out = self.LinNet(x)          # 通过全连接层
        return out

